<?php

class MSN_Protocol {

    public $helper      = null;
    public $connection  = null;

    public function __construct( $parent ) {
        $this->helper       = &$parent->helper;
        $this->connection   = &$parent->connection;        
    } // end func

    public function answerCVR() {
        $this->connection->writeLn( 'USR', sprintf('SSO I %s', $this->helper->user ));
    } // end func

    public function answerVER() {
        $this->connection->writeLn('CVR', sprintf('0x0409 winnt 5.1 i386 MSMSGS %s msmsgs %s', $this->helper->buildver, $this->helper->user));
    } // end func

    public function answerXFR( $data ) {
        // NS: <<< XFR {id} NS {server} U D
        @list(/* XFR */, /* id */, /* NS */, $server, /* ... */) = @explode(' ', $data);
        @list($ip, $port) = @explode(':', $server);
        
        $this->helper->log(sprintf('Redirected to another server: %s:%d', $ip, $port));

        $this->connection->init( $ip, $port );        
    } // end func

    public function answerGCF( $data ) {
        @list(/* GCF */, /* 0 */, $size,) = @explode(' ', $data);

        if (is_numeric($size) && $size > 0) {
            $this->connection->readData($size, true);
            $this->helper->debug('NS: <<< Got some Policy data');
        }
    } // end func


    public function answerUSR( $data ) {
        // already login for passport site, finish the login process now.
        // NS: <<< USR {id} OK {user} {verify} 0
        if ( $this->helper->authed )
            return true;

        // max. 16 digits for password
        if (strlen($this->helper->password) > 16)
            $this->helper->password = substr($this->helper->password, 0, 16);


        // NS: <<< USR {id} SSO S {policy} {nonce}
        @list(/* USR */, /* id */, /* SSO */, /* S */, $policy, $nonce,) = @explode(' ', $data);

        $this->helper->passport_policy = $policy;
        $aTickets = $this->helper->getPassportTickets();
        if (!$aTickets || !is_array($aTickets)) {
            $this->helper->logoutError('Passport authenticated fail!');
            return false;
        }

        $ticket                 = $aTickets['ticket'];
        $secret                 = $aTickets['secret'];
        $this->helper->oim_ticket       = $aTickets['oim_ticket'];
        $this->helper->contact_ticket   = $aTickets['contact_ticket'];
        $this->helper->web_ticket       = $aTickets['web_ticket'];
        $this->helper->space_ticket     = $aTickets['space_ticket'];
        $this->helper->storage_ticket   = $aTickets['storage_ticket'];

        $login_code             = $this->helper->generateLoginBLOB($secret, $nonce);

        // NS: >>> USR {id} SSO S {ticket} {login_code}
        $this->connection->writeLn('USR', sprintf('SSO S %s %s', $ticket, $login_code));

        $this->helper->authed = true;        
    } // end func

    public function sendADL( $contactList ) {
        $n = 0;
        $sList = '';
        $len = 0;
        $aADL = array();

        if (is_array($contactList)) {
            foreach ($contactList as $u_domain => $aUserList) {
                $str = sprintf('<d n="%s">', $u_domain);
                $len += strlen($str);

                if ($len > 7400) {
                    $aADL[$n] = sprintf('<ml l="1">%s</ml>', $sList);
                    $n++;
                    $sList = '';
                    $len = strlen($str);
                }
                $sList .= $str;
                foreach ($aUserList as $u_name => $aNetworks) {
                    foreach ($aNetworks as $network => $status) {
                        $str = sprintf('<c n="%s" l="3" t="%s" />', $u_name, $network);
                        $len += strlen($str);
                        // max: 7500, but <ml l="1"></d></ml> is 19,
                        // so we use 7475
                        if ($len > 7475) {
                            $sList .= '</d>';
                            $aADL[$n] = sprintf('<ml l="1">%s</ml>', $sList);
                            $n++;
                            $sList = sprintf('<d n="%s">', $u_domain).$str;
                            $len = strlen($sList);
                        }
                        else
                            $sList .= $str;
                    }
                }
                $sList .= '</d>';
            }
        }
        $aADL[$n] = sprintf('<ml l="1">%s</ml>', $sList);
        // NS: >>> BLP {id} BL
        $this->connection->writeLn('BLP ', ' BL');
        foreach ($aADL as $str) {
            $len = strlen($str);
            // NS: >>> ADL {id} {size}
            $this->connection->writeLn('ADL ', $len);
            $this->connection->writeData($str);
        }        
    } // end func

    public function answerMSG( $data ) {
        // randomly, we get MSG notification from server
        // NS: <<< MSG Hotmail Hotmail {size}
        @list(/* MSG */, /* Hotmail */, /* Hotmail */, $size,) = @explode(' ', $data);
        
        if (is_numeric($size) && $size > 0) {
            $data = $this->connection->ReadData($size);
            $aLines = @explode("\n", $data);
            $header = true;
            $ignore = false;
            $maildata = '';
        }
    } // end func

    public function answerUBX( $data ) {
        // randomly, we get UBX notification from server
        // NS: <<< UBX email {network} {size}
        @list(/* UBX */, /* email */, /* network */, $size,) = @explode(' ', $data);
        // we don't need the notification data, so just ignore it
        if (is_numeric($size) && $size > 0)
            $this->connection->ReadData($size);        
    } // end func

    public function answerCHL( $data ) {
        // randomly, we'll get challenge from server
        // NS: <<< CHL 0 {code}
        @list(/* CHL */, /* 0 */, $chl_code,) = @explode(' ', $data);
        $fingerprint = $this->helper->getChallenge($chl_code);
        // NS: >>> QRY {id} {product_id} 32
        // NS: >>> fingerprint
        $this->connection->writeLn('QRY', sprintf('%s 32', $this->helper->prod_id));
        $this->connection->writeData($fingerprint);        
    } // end func


    public function answerLST( $data, $aContactList ) {
        // NS: <<< LST {email} {alias} 11 0
        @list(/* LST */, $email, /* alias */, ) = @explode(' ', $data);
        @list($u_name, $u_domain) = @explode('@', $email);
        if (!isset($aContactList[$u_domain][$u_name][1])) {
            $aContactList[$u_domain][$u_name][1]['Allow'] = 'Allow';
            $this->helper->log("add to our contact list: $u_name@$u_domain");
        }        
    } // end func

    public function parseILN( $data ) {
        $result = array();
        @list(/* ILN */, /* 0 */, $result['status'], $result['email'], /* 1 */,$result['nick']) = @explode(' ', $data);
        return $result;
    } // end func
} // end class

?>